package com.benefm.multipar.pad.util.resp;

import java.util.ArrayList;

public class BrAlgorithm {
    public static final int MAX_RESP_DATA_SECOND = 30;  // 最长30秒数据
    private static final float DIFF_WINDOWS_WIDTH_RATE = (float) 0.2;
    private static final float NO_RESPONSE_RATE = (float) 0.8;  // Modified by monfore 20230718   1-->0.8
    private static final int MIN_DETECT_DIFF_VALUE = 1000;
    private static final int MAX_DETECT_DIFF_VALUE = 8000000;   // Added by monfore 20230718
    private static final int MIN_VALUE_DIFF = 5;                // Added by monfore 20230718
    private static final int MAX_BR = 65;                       // Added by monfore 20230718
    private static final int MIN_DATA_SECONDS = 5;

    int m_nDetectPeckTh;
    int DIFF_WINDOWS_WIDTH;
    int NO_RESPONSE_WIDHT;

    ArrayList<Integer> m_vctPeakLocations;
    ArrayList<Integer> m_vctPeakValues;
    ArrayList<Integer> m_vctDiffValue;

    public BrAlgorithm() {
        reset();
    }

    public void reset() {
        m_nDetectPeckTh = 100;
        m_vctPeakLocations = new ArrayList<>();
        m_vctPeakValues = new ArrayList<>();
        m_vctDiffValue = new ArrayList<>();
    }


    private void calcDiffValue(int[] xDataBuf) {
        int i;
        int diffValue;

        m_vctDiffValue.clear();

        do {
            if (null == xDataBuf) {
                break;
            }
            if (DIFF_WINDOWS_WIDTH * 2 >= xDataBuf.length) {
                break;
            }
            for (i = 0; i < DIFF_WINDOWS_WIDTH; i++) {
                diffValue = (xDataBuf[i] - 0) * (xDataBuf[i] - xDataBuf[i + DIFF_WINDOWS_WIDTH]);
                m_vctDiffValue.add(diffValue);
            }
            for (i = DIFF_WINDOWS_WIDTH; i < xDataBuf.length - DIFF_WINDOWS_WIDTH; i++) {
                diffValue = (xDataBuf[i] - xDataBuf[i - DIFF_WINDOWS_WIDTH]) * (xDataBuf[i] - xDataBuf[i + DIFF_WINDOWS_WIDTH]);
                m_vctDiffValue.add(diffValue);
            }

            for (i = xDataBuf.length - DIFF_WINDOWS_WIDTH; i < xDataBuf.length; i++) {
                diffValue = (xDataBuf[i] - xDataBuf[i - DIFF_WINDOWS_WIDTH]) * (xDataBuf[i] - 0);
                m_vctDiffValue.add(diffValue);
            }
        } while (false);
    }

//    private void calcDiffValue(CircularFifoQueue<Integer> listDataBuf) {
//        int i;
//        int diffValue;
//
//        m_vctDiffValue.clear();
//
//        do {
//            if (null == listDataBuf) {
//                break;
//            }
//            if (DIFF_WINDOWS_WIDTH * 2 >= listDataBuf.size()) {
//                break;
//            }
//            for (i = 0; i < DIFF_WINDOWS_WIDTH; i++) {
//                diffValue = (listDataBuf.get(i) - 0) * (listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH));
//                m_vctDiffValue.add(diffValue);
//            }
//            for (i = DIFF_WINDOWS_WIDTH; i < listDataBuf.size() - DIFF_WINDOWS_WIDTH; i++) {
//                diffValue = (listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH)) * (listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH));
//                m_vctDiffValue.add(diffValue);
//            }
//
//            for (i = listDataBuf.size() - DIFF_WINDOWS_WIDTH; i < listDataBuf.size(); i++) {
//                diffValue = (listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH)) * (listDataBuf.get(i) - 0);
//                m_vctDiffValue.add(diffValue);
//            }
//        } while (false);
//    }

    private void calcDiffValue(ArrayList<Integer> listDataBuf) {
        int i;
        int diffValue;

        m_vctDiffValue.clear();

        do {
            if (null == listDataBuf) {
                break;
            }
            if (DIFF_WINDOWS_WIDTH * 2 >= listDataBuf.size()) {
                break;
            }
            for (i = 0; i < DIFF_WINDOWS_WIDTH; i++) {
                diffValue = (listDataBuf.get(i) - 0) * (listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH));
                m_vctDiffValue.add(diffValue);
            }
            for (i = DIFF_WINDOWS_WIDTH; i < listDataBuf.size() - DIFF_WINDOWS_WIDTH; i++) {
                diffValue = (listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH)) * (listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH));
                m_vctDiffValue.add(diffValue);
            }

            for (i = listDataBuf.size() - DIFF_WINDOWS_WIDTH; i < listDataBuf.size(); i++) {
                diffValue = (listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH)) * (listDataBuf.get(i) - 0);
                m_vctDiffValue.add(diffValue);
            }
        } while (false);
    }


    private int findDiffPeaks(int[] xDataBuf) {
        int i, j;
        int preDiffValue = 0;
        int postDiffValue = 0;
        int nDiffValue = 0;

        do {
            m_vctPeakValues.clear(); //peak
            m_vctPeakLocations.clear(); // location

            if (null == xDataBuf) {
                break;
            }
            if (0 >= xDataBuf.length) {
                break;
            }
            if (m_vctDiffValue.size() != xDataBuf.length) {
                break;
            }
            int nLength = m_vctDiffValue.size();
            if (0 >= m_vctDiffValue.size()) {
                break;
            }

            for (i = DIFF_WINDOWS_WIDTH; i < nLength; i++) {
                if ((i + NO_RESPONSE_WIDHT) > nLength) {
                    break;
                }
                if ((i + DIFF_WINDOWS_WIDTH) >= nLength) {
                    break;
                }
                if (m_vctDiffValue.get(i) < 0) {
                    continue;
                }
                if (MAX_DETECT_DIFF_VALUE < m_vctDiffValue.get(i)) {
                    continue;
                }
                if (m_vctDiffValue.get(i) < m_vctDiffValue.get(i - 1)) {
                    continue;
                }

                for (j = i; j < i + NO_RESPONSE_WIDHT; j++) {
                    // Added by monfore 20230718
                    if (xDataBuf[j] < xDataBuf[i]) {
                        continue;
                    }
                    // End of Added by monfore 20230718
                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
                        break;
                    }
                }
                if (j < (i + NO_RESPONSE_WIDHT)) {
                    continue;
                }
                if ((0 < m_vctPeakLocations.size()) && (m_vctPeakLocations.get(m_vctPeakLocations.size() - 1) + NO_RESPONSE_WIDHT) > i) {
                    if (m_vctPeakValues.get(m_vctPeakValues.size() - 1) >= m_vctDiffValue.get(i)) {
                        continue;
                    }
                }
                // check Peak Value
                for (j = i, preDiffValue = 0; j >= DIFF_WINDOWS_WIDTH; j--) {
                    if (0 <= m_vctDiffValue.get(j)) {
                        continue;
                    }
                    // Modified by monfore 20230718
                    if ((m_vctDiffValue.get(j) < m_vctDiffValue.get(j - 1)) && (m_vctDiffValue.get(j - 1) <= m_vctDiffValue.get(j - 2)) && (m_vctDiffValue.get(j - 2) <= m_vctDiffValue.get(j - 3))) {
                        if (m_vctDiffValue.get(i) > m_vctDiffValue.get(j)) {
                            preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
                        }
                        break;
                    }
                    // End of Modified by monfore 20230718
                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
                        break;
                    }
                    preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
                }
                for (j = i, postDiffValue = 0; j < nLength - 1; j++) {
                    if (j > (i + DIFF_WINDOWS_WIDTH)) {
                        break;
                    }
                    if (0 <= m_vctDiffValue.get(j)) {
                        continue;
                    }
                    // Modified by monfore 20230718
                    if (((j == (nLength - 1)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1))) ||
                            ((j == (nLength - 2)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1)) && (m_vctDiffValue.get(j) <= m_vctDiffValue.get(j + 2))) ||
                            ((j <= (nLength - 3)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1)) && (m_vctDiffValue.get(j) <= m_vctDiffValue.get(j + 2)) && (m_vctDiffValue.get(j + 2) <= m_vctDiffValue.get(j + 3)))) {
                        if (m_vctDiffValue.get(i) > m_vctDiffValue.get(j)) {
                            preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
                        }
                        break;
                    }
                    // End of Modified by monfore 20230718
                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
                        break;
                    }
                    postDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
                }
                nDiffValue = preDiffValue > postDiffValue ? preDiffValue : postDiffValue;
                if (MIN_DETECT_DIFF_VALUE > nDiffValue) {
                    continue;
                }
                // Added by monfore 20230718
                if (MAX_DETECT_DIFF_VALUE < nDiffValue) {
                    continue;
                }
                // End of Added by monfore 20230718
                if (DIFF_WINDOWS_WIDTH <= i) {
                    if ((xDataBuf[i] < xDataBuf[i - DIFF_WINDOWS_WIDTH]) || (xDataBuf[i] < xDataBuf[i + DIFF_WINDOWS_WIDTH])) {
                        continue;
                    }
                    // Added by monfore 20230718
                    if ((Math.abs(xDataBuf[i] - xDataBuf[i - DIFF_WINDOWS_WIDTH]) < MIN_VALUE_DIFF) &&
                            (Math.abs(xDataBuf[i] - xDataBuf[i - DIFF_WINDOWS_WIDTH / 2]) < MIN_VALUE_DIFF) &&
                            (Math.abs(xDataBuf[i] - xDataBuf[i + DIFF_WINDOWS_WIDTH / 2]) < MIN_VALUE_DIFF)) {
                        continue;
                    }
                    if ((Math.abs(xDataBuf[i] - xDataBuf[i - DIFF_WINDOWS_WIDTH / 2]) < MIN_VALUE_DIFF) &&
                            (Math.abs(xDataBuf[i] - xDataBuf[i + DIFF_WINDOWS_WIDTH / 2]) < MIN_VALUE_DIFF) &&
                            (Math.abs(xDataBuf[i] - xDataBuf[i + DIFF_WINDOWS_WIDTH]) < MIN_VALUE_DIFF)) {
                        continue;
                    }
                    // End of Added by monfore 20230718
                } else {
                    if ((xDataBuf[i] < 0) || (xDataBuf[i] < xDataBuf[i] + DIFF_WINDOWS_WIDTH)) {
                        continue;
                    }
                }
                // Added by monfore 20230718
                if ((0 < m_vctPeakLocations.size()) && ((m_vctPeakLocations.get(m_vctPeakLocations.size() - 1) + NO_RESPONSE_WIDHT) > i)) {
                    continue;
                }
                // End of Added by monfore 20230718
                // Peak
                m_vctPeakValues.add(m_vctDiffValue.get(i)); //peak
                m_vctPeakLocations.add(i); // location
            }
        } while (false);
        return m_vctPeakLocations.size();
    }

//    private int findDiffPeaks(CircularFifoQueue<Integer> listDataBuf) {
//        int i, j;
//        int preDiffValue = 0;
//        int postDiffValue = 0;
//        int nDiffValue = 0;
//
//        do {
//            m_vctPeakValues.clear(); //peak
//            m_vctPeakLocations.clear(); // location
//
//            if (null == listDataBuf) {
//                break;
//            }
//            if (0 >= listDataBuf.size()) {
//                break;
//            }
//            if (m_vctDiffValue.size() != listDataBuf.size()) {
//                break;
//            }
//            int nLength = m_vctDiffValue.size();
//            if (0 >= m_vctDiffValue.size()) {
//                break;
//            }
//
//            for (i = DIFF_WINDOWS_WIDTH; i < nLength; i++) {
//                if ((i + NO_RESPONSE_WIDHT) > nLength) {
//                    break;
//                }
//                if ((i + DIFF_WINDOWS_WIDTH) >= nLength) {
//                    break;
//                }
//                if (m_vctDiffValue.get(i) < 0) {
//                    continue;
//                }
//                if (MAX_DETECT_DIFF_VALUE < m_vctDiffValue.get(i)) {
//                    continue;
//                }
//                if (m_vctDiffValue.get(i) < m_vctDiffValue.get(i - 1)) {
//                    continue;
//                }
//
//                for (j = i; j < i + NO_RESPONSE_WIDHT; j++) {
//                    // Added by monfore 20230718
//                    if (listDataBuf.get(j) < listDataBuf.get(i)) {
//                        continue;
//                    }
//                    // End of Added by monfore 20230718
//                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
//                        break;
//                    }
//                }
//                if (j < (i + NO_RESPONSE_WIDHT)) {
//                    continue;
//                }
//                if ((0 < m_vctPeakLocations.size()) && (m_vctPeakLocations.get(m_vctPeakLocations.size() - 1) + NO_RESPONSE_WIDHT) > i) {
//                    if (m_vctPeakValues.get(m_vctPeakValues.size() - 1) >= m_vctDiffValue.get(i)) {
//                        continue;
//                    }
//                }
//                // check Peak Value
//                for (j = i, preDiffValue = 0; j >= DIFF_WINDOWS_WIDTH; j--) {
//                    if (0 <= m_vctDiffValue.get(j)) {
//                        continue;
//                    }
//                    // Modified by monfore 20230718
//                    if ((m_vctDiffValue.get(j) < m_vctDiffValue.get(j - 1)) && (m_vctDiffValue.get(j - 1) <= m_vctDiffValue.get(j - 2)) && (m_vctDiffValue.get(j - 2) <= m_vctDiffValue.get(j - 3))) {
//                        if (m_vctDiffValue.get(i) > m_vctDiffValue.get(j)) {
//                            preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
//                        }
//                        break;
//                    }
//                    // End of Modified by monfore 20230718
//                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
//                        break;
//                    }
//                    preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
//                }
//                for (j = i, postDiffValue = 0; j < nLength - 1; j++) {
//                    if (j > (i + DIFF_WINDOWS_WIDTH)) {
//                        break;
//                    }
//                    if (0 <= m_vctDiffValue.get(j)) {
//                        continue;
//                    }
//                    // Modified by monfore 20230718
//                    if (((j == (nLength - 1)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1))) ||
//                            ((j == (nLength - 2)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1)) && (m_vctDiffValue.get(j) <= m_vctDiffValue.get(j + 2))) ||
//                            ((j <= (nLength - 3)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1)) && (m_vctDiffValue.get(j) <= m_vctDiffValue.get(j + 2)) && (m_vctDiffValue.get(j + 2) <= m_vctDiffValue.get(j + 3)))) {
//                        if (m_vctDiffValue.get(i) > m_vctDiffValue.get(j)) {
//                            preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
//                        }
//                        break;
//                    }
//                    // End of Modified by monfore 20230718
//                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
//                        break;
//                    }
//                    postDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
//                }
//                nDiffValue = preDiffValue > postDiffValue ? preDiffValue : postDiffValue;
//                if (MIN_DETECT_DIFF_VALUE > nDiffValue) {
//                    continue;
//                }
//                // Added by monfore 20230718
//                if (MAX_DETECT_DIFF_VALUE < nDiffValue) {
//                    continue;
//                }
//                // End of Added by monfore 20230718
//                if (DIFF_WINDOWS_WIDTH <= i) {
//                    if ((listDataBuf.get(i) < listDataBuf.get(i - DIFF_WINDOWS_WIDTH)) || (listDataBuf.get(i) < listDataBuf.get(i + DIFF_WINDOWS_WIDTH))) {
//                        continue;
//                    }
//                    // Added by monfore 20230718
//                    if ((Math.abs(listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH)) < MIN_VALUE_DIFF) &&
//                            (Math.abs(listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH / 2)) < MIN_VALUE_DIFF) &&
//                            (Math.abs(listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH / 2)) < MIN_VALUE_DIFF)) {
//                        continue;
//                    }
//                    if ((Math.abs(listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH / 2)) < MIN_VALUE_DIFF) &&
//                            (Math.abs(listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH / 2)) < MIN_VALUE_DIFF) &&
//                            (Math.abs(listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH)) < MIN_VALUE_DIFF)) {
//                        continue;
//                    }
//                    // End of Added by monfore 20230718
//                } else {
//                    if ((listDataBuf.get(i) < 0) || (listDataBuf.get(i) < listDataBuf.get(i) + DIFF_WINDOWS_WIDTH)) {
//                        continue;
//                    }
//                }
//
//                // Added by monfore 20230718
//                if ((0 < m_vctPeakLocations.size()) && ((m_vctPeakLocations.get(m_vctPeakLocations.size() - 1) + NO_RESPONSE_WIDHT) > i)) {
//                    continue;
//                }
//                // End of Added by monfore 20230718
//                // Peak
//                m_vctPeakValues.add(m_vctDiffValue.get(i)); //peak
//                m_vctPeakLocations.add(i); // location
//            }
//        } while (false);
//        return m_vctPeakLocations.size();
//    }

    private int findDiffPeaks(ArrayList<Integer> listDataBuf) {
        int i, j;
        int preDiffValue = 0;
        int postDiffValue = 0;
        int nDiffValue = 0;

        do {
            m_vctPeakValues.clear(); //peak
            m_vctPeakLocations.clear(); // location

            if (null == listDataBuf) {
                break;
            }
            if (0 >= listDataBuf.size()) {
                break;
            }
            if (m_vctDiffValue.size() != listDataBuf.size()) {
                break;
            }
            int nLength = m_vctDiffValue.size();
            if (0 >= m_vctDiffValue.size()) {
                break;
            }

            for (i = DIFF_WINDOWS_WIDTH; i < nLength; i++) {
                if ((i + NO_RESPONSE_WIDHT) > nLength) {
                    break;
                }
                if ((i + DIFF_WINDOWS_WIDTH) >= nLength) {
                    break;
                }
                if (m_vctDiffValue.get(i) < 0) {
                    continue;
                }
                if (MAX_DETECT_DIFF_VALUE < m_vctDiffValue.get(i)) {
                    continue;
                }
                if (m_vctDiffValue.get(i) < m_vctDiffValue.get(i - 1)) {
                    continue;
                }

                for (j = i; j < i + NO_RESPONSE_WIDHT; j++) {
                    // Added by monfore 20230718
                    if (listDataBuf.get(j) < listDataBuf.get(i)) {
                        continue;
                    }
                    // End of Added by monfore 20230718
                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
                        break;
                    }
                }
                if (j < (i + NO_RESPONSE_WIDHT)) {
                    continue;
                }
                if ((0 < m_vctPeakLocations.size()) && (m_vctPeakLocations.get(m_vctPeakLocations.size() - 1) + NO_RESPONSE_WIDHT) > i) {
                    if (m_vctPeakValues.get(m_vctPeakValues.size() - 1) >= m_vctDiffValue.get(i)) {
                        continue;
                    }
                }
                // check Peak Value
                for (j = i, preDiffValue = 0; j >= DIFF_WINDOWS_WIDTH; j--) {
                    if (0 <= m_vctDiffValue.get(j)) {
                        continue;
                    }
                    // Modified by monfore 20230718
                    if ((m_vctDiffValue.get(j) < m_vctDiffValue.get(j - 1)) && (m_vctDiffValue.get(j - 1) <= m_vctDiffValue.get(j - 2)) && (m_vctDiffValue.get(j - 2) <= m_vctDiffValue.get(j - 3))) {
                        if (m_vctDiffValue.get(i) > m_vctDiffValue.get(j)) {
                            preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
                        }
                        break;
                    }
                    // End of Modified by monfore 20230718
                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
                        break;
                    }
                    preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
                }
                for (j = i, postDiffValue = 0; j < nLength - 1; j++) {
                    if (j > (i + DIFF_WINDOWS_WIDTH)) {
                        break;
                    }
                    if (0 <= m_vctDiffValue.get(j)) {
                        continue;
                    }
                    // Modified by monfore 20230718
                    if (((j == (nLength - 1)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1))) ||
                            ((j == (nLength - 2)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1)) && (m_vctDiffValue.get(j) <= m_vctDiffValue.get(j + 2))) ||
                            ((j <= (nLength - 3)) && (m_vctDiffValue.get(j) < m_vctDiffValue.get(j + 1)) && (m_vctDiffValue.get(j) <= m_vctDiffValue.get(j + 2)) && (m_vctDiffValue.get(j + 2) <= m_vctDiffValue.get(j + 3)))) {
                        if (m_vctDiffValue.get(i) > m_vctDiffValue.get(j)) {
                            preDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
                        }
                        break;
                    }
                    // End of Modified by monfore 20230718
                    if (m_vctDiffValue.get(i) < m_vctDiffValue.get(j)) {
                        break;
                    }
                    postDiffValue = m_vctDiffValue.get(i) - m_vctDiffValue.get(j);
                }
                nDiffValue = preDiffValue > postDiffValue ? preDiffValue : postDiffValue;
                if (MIN_DETECT_DIFF_VALUE > nDiffValue) {
                    continue;
                }
                // Added by monfore 20230718
                if (MAX_DETECT_DIFF_VALUE < nDiffValue) {
                    continue;
                }
                // End of Added by monfore 20230718
                if (DIFF_WINDOWS_WIDTH <= i) {
                    if ((listDataBuf.get(i) < listDataBuf.get(i - DIFF_WINDOWS_WIDTH)) || (listDataBuf.get(i) < listDataBuf.get(i + DIFF_WINDOWS_WIDTH))) {
                        continue;
                    }
                    // Added by monfore 20230718
                    if ((Math.abs(listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH)) < MIN_VALUE_DIFF) &&
                            (Math.abs(listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH / 2)) < MIN_VALUE_DIFF) &&
                            (Math.abs(listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH / 2)) < MIN_VALUE_DIFF)) {
                        continue;
                    }
                    if ((Math.abs(listDataBuf.get(i) - listDataBuf.get(i - DIFF_WINDOWS_WIDTH / 2)) < MIN_VALUE_DIFF) &&
                            (Math.abs(listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH / 2)) < MIN_VALUE_DIFF) &&
                            (Math.abs(listDataBuf.get(i) - listDataBuf.get(i + DIFF_WINDOWS_WIDTH)) < MIN_VALUE_DIFF)) {
                        continue;
                    }
                    // End of Added by monfore 20230718
                } else {
                    if ((listDataBuf.get(i) < 0) || (listDataBuf.get(i) < listDataBuf.get(i) + DIFF_WINDOWS_WIDTH)) {
                        continue;
                    }
                }

                // Added by monfore 20230718
                if ((0 < m_vctPeakLocations.size()) && ((m_vctPeakLocations.get(m_vctPeakLocations.size() - 1) + NO_RESPONSE_WIDHT) > i)) {
                    continue;
                }
                // End of Added by monfore 20230718
                // Peak
                m_vctPeakValues.add(m_vctDiffValue.get(i)); //peak
                m_vctPeakLocations.add(i); // location
            }
        } while (false);
        return m_vctPeakLocations.size();
    }

    int calcBR(int[] xDataBuf, int sampleRate) {
        int br = -1;

        do {
            if (null == xDataBuf) {
                break;
            }
            if (0 >= sampleRate) {
                break;
            }
            int nMinDataLen = sampleRate * 5;//MIN_DATA_SECONDS;
            if (nMinDataLen > xDataBuf.length) {
                break;
            }

            DIFF_WINDOWS_WIDTH = (int) (sampleRate * DIFF_WINDOWS_WIDTH_RATE);
            NO_RESPONSE_WIDHT = (int) (sampleRate * NO_RESPONSE_RATE);
            m_nDetectPeckTh = 100;

//        int numberOfPeaks = findPeaks(pDataBuf, length);

            calcDiffValue(xDataBuf);
            int numberOfPeaks = findDiffPeaks(xDataBuf);
            int currBR = 0;
            int SumBR = 0;
            int pos1, pos2;
            float foSeconds;

//        std::cout<<"**************************************************"<<std::endl;
            float foRemain = 0;
            for (int i = 1; i < m_vctPeakLocations.size(); i++) {
                pos1 = m_vctPeakLocations.get(i);
                pos2 = m_vctPeakLocations.get(i - 1);
                foSeconds = (float) (pos1 - pos2) / sampleRate;
                currBR = (int) (60 / foSeconds);//(float)((m_vctPeakLocations[i]-m_vctPeakLocations[i-1])/sampleRate);
                foRemain = 60 / foSeconds - currBR;
                if (foRemain >= 0.50001) {
                    currBR += 1;
                }
                if (MAX_BR <= currBR) {
                    continue;
                }
                SumBR += currBR;
                br = SumBR / i;
                foRemain = SumBR / i - br;
                if (foRemain >= 0.50001) {
                    br += 1;
                }
//            pos1 = pos2;
                System.out.println("calcBR ::  currBR = " + currBR + "  RR = " + foSeconds + "  Avg BR = " + br);
            }
//        if(1 < numberOfPeaks){
//            br = 60/(float)((float)((float)(m_vctPeakLocations[numberOfPeaks-1]-m_vctPeakLocations[0])/(float)sampleRate)/(float)(numberOfPeaks-1));
//            std::cout<<"calcBR :: 2 br = "<<br<<"  "<<m_vctPeakLocations[numberOfPeaks-1]<<"-"<<m_vctPeakLocations[0]<<" = "<<m_vctPeakLocations[numberOfPeaks-1]-m_vctPeakLocations[0]<<"  Avg RR = "<<(float)((float)((float)(m_vctPeakLocations[numberOfPeaks-1]-m_vctPeakLocations[0])/(float)sampleRate)/(float)(numberOfPeaks-1))<<std::endl;
//        }
//        std::cout<<"calcBR ::  BR = "<<br<<"  number = "<<numberOfPeaks<<std::endl;
//        std::cout<<"**************************************************"<<std::endl;

            m_vctPeakValues.clear();
            m_vctPeakLocations.clear();
        } while (false);

        return br;
    }

//    public int calcBR(CircularFifoQueue<Integer> listData, int sampleRate) {
//        int br = -1;
//        do {
//            if (null == listData) {
//                break;
//            }
//            if (0 >= sampleRate) {
//                break;
//            }
//            int nMinDataLen = sampleRate * 5;//MIN_DATA_SECONDS;
//            if (nMinDataLen > listData.size()) {
//                break;
//            }
//
//            DIFF_WINDOWS_WIDTH = (int) (sampleRate * DIFF_WINDOWS_WIDTH_RATE);
//            NO_RESPONSE_WIDHT = (int) (sampleRate * NO_RESPONSE_RATE);
//            m_nDetectPeckTh = 100;
//
////        int numberOfPeaks = findPeaks(pDataBuf, length);
//
//            calcDiffValue(listData);
//            int numberOfPeaks = findDiffPeaks(listData);
//            int currBR = 0;
//            int SumBR = 0;
//            int pos1, pos2;
//            float foSeconds;
//
////        std::cout<<"**************************************************"<<std::endl;
//            float foRemain = 0;
//            for (int i = 1; i < m_vctPeakLocations.size(); i++) {
//                pos1 = m_vctPeakLocations.get(i);
//                pos2 = m_vctPeakLocations.get(i - 1);
//                foSeconds = (float) (pos1 - pos2) / sampleRate;
//                currBR = (int) (60 / foSeconds);//(float)((m_vctPeakLocations[i]-m_vctPeakLocations[i-1])/sampleRate);
//                foRemain = 60 / foSeconds - currBR;
//                if (foRemain >= 0.50001) {
//                    currBR += 1;
//                }
//                if (MAX_BR <= currBR) {
//                    continue;
//                }
//                SumBR += currBR;
//                br = SumBR / i;
//                foRemain = SumBR / i - br;
//                if (foRemain >= 0.50001) {
//                    br += 1;
//                }
////                System.out.println("calcBR ::  currBR = "+currBR+"  RR = "+foSeconds+"  Avg BR = "+br);
//            }
//
//            m_vctPeakValues.clear();
//            m_vctPeakLocations.clear();
//        } while (false);
//
//        return br;
//    }


    public int calcBR(ArrayList<Integer> listData, int sampleRate) {
        int br = -1;
        do {
            if (null == listData) {
                break;
            }
            if (0 >= sampleRate) {
                break;
            }
            int nMinDataLen = sampleRate * 5;//MIN_DATA_SECONDS;
            if (nMinDataLen > listData.size()) {
                break;
            }

            DIFF_WINDOWS_WIDTH = (int) (sampleRate * DIFF_WINDOWS_WIDTH_RATE);
            NO_RESPONSE_WIDHT = (int) (sampleRate * NO_RESPONSE_RATE);
            m_nDetectPeckTh = 100;

//        int numberOfPeaks = findPeaks(pDataBuf, length);

            calcDiffValue(listData);
            int numberOfPeaks = findDiffPeaks(listData);
            int currBR = 0;
            int SumBR = 0;
            int pos1, pos2;
            float foSeconds;

//        std::cout<<"**************************************************"<<std::endl;
            float foRemain = 0;
            for (int i = 1; i < m_vctPeakLocations.size(); i++) {
                pos1 = m_vctPeakLocations.get(i);
                pos2 = m_vctPeakLocations.get(i - 1);
                foSeconds = (float) (pos1 - pos2) / sampleRate;
                currBR = (int) (60 / foSeconds);//(float)((m_vctPeakLocations[i]-m_vctPeakLocations[i-1])/sampleRate);
                foRemain = 60 / foSeconds - currBR;
                if (foRemain >= 0.50001) {
                    currBR += 1;
                }
                if (MAX_BR <= currBR) {
                    continue;
                }
                SumBR += currBR;
                br = SumBR / i;
                foRemain = SumBR / i - br;
                if (foRemain >= 0.50001) {
                    br += 1;
                }
//                System.out.println("calcBR ::  currBR = "+currBR+"  RR = "+foSeconds+"  Avg BR = "+br);
            }

            m_vctPeakValues.clear();
            m_vctPeakLocations.clear();
        } while (false);

        return br;
    }
}
